﻿using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using StardewModdingAPI;
using StardewModdingAPI.Events;
using StardewValley;
using StardewValley.Menus;
using StardewValley.Objects;
using StardewValley.Tools;

namespace WorseGame.Content
{
    public class 负重系统(IMonitor 监视器, IModHelper 助手)
    {
        private readonly IMonitor 监视器 = 监视器;
        private readonly IModHelper 助手 = 助手;
        private const int 基础负重上限 = 100;
        private const int 超重阈值 = 120;
        private const int 严重超重阈值 = 150;
        private const float 超重减速比例 = 0.3f;
        private const float 严重超重减速比例 = 0.6f;
        private float 原始移动速度 = 0f;
        private bool 已应用减速 = false;

        public void Initialize()
        {
            助手.Events.GameLoop.UpdateTicked += 更新时触发;
            助手.Events.GameLoop.SaveLoaded += 存档加载时;
            助手.Events.Display.RenderedActiveMenu += 渲染菜单时;
        }

        private void 存档加载时(object? sender, SaveLoadedEventArgs e)
        {
            原始移动速度 = Game1.player.Speed;
        }

        private void 更新时触发(object? sender, UpdateTickedEventArgs e)
        {
            if (!Context.IsWorldReady || Game1.player == null)
                return;

            if (e.IsMultipleOf(60))
            {
                检查并应用负重效果();
            }
        }

        private void 检查并应用负重效果()
        {
            int 当前负重 = 计算当前负重();           
            if (当前负重 >= 严重超重阈值)
            {
                应用移动减速(严重超重减速比例);
            }
            else if (当前负重 >= 超重阈值)
            {
                应用移动减速(超重减速比例);
            }
            else
            {
                恢复移动速度();
            }
        }

        private static int 计算当前负重()
        {
            int 总负重 = 0;

            foreach (var 物品 in Game1.player.Items)
            {
                if (物品 != null && 物品.Stack > 0)
                {
                    int 物品重量 = 计算物品重量(物品);
                    总负重 += 物品重量 * 物品.Stack;
                }
            }

            return 总负重;
        }

        private static int 计算物品重量(Item 物品)
        {
            return 物品 switch
            {
                Axe => 5, // 斧头
                Pickaxe => 7, // 镐
                Hoe => 4, // 锄头
                WateringCan => 6, // 喷壶
                FishingRod => 3, // 钓鱼竿
                MeleeWeapon => 10, // 近战武器
                Hat => 2, // 帽子
                Boots => 4, // 鞋子
                Ring => 1, // 戒指
                Clothing => 3, // 衣服
                Furniture => 15, // 家具
                _ => 2
            };
        }

        private void 应用移动减速(float 减速比例)
        {
            if (!已应用减速)
            {
                原始移动速度 = Game1.player.Speed;
                已应用减速 = true;
            }

            Game1.player.Speed = (int)(原始移动速度 * (1 - 减速比例));
        }

        private void 恢复移动速度()
        {
            if (已应用减速)
            {
                Game1.player.Speed = (int)原始移动速度;
                已应用减速 = false;
            }
        }

        private void 渲染菜单时(object? sender, RenderedActiveMenuEventArgs e)
        {
            if (Game1.activeClickableMenu is GameMenu 游戏菜单)
            {
                var 当前页面 = 助手.Reflection.GetField<List<IClickableMenu>>(游戏菜单, "pages").GetValue();
                if (当前页面.Count > 0 && 当前页面[0] is InventoryPage 背包页面)
                {
                    显示背包负重信息(e.SpriteBatch, 背包页面);
                }
            }
        }

        private static void 显示背包负重信息(SpriteBatch spriteBatch, InventoryPage 背包页面)
        {
            int 当前负重 = 计算当前负重();
            float 负重比例 = (float)当前负重 / 基础负重上限;
            int 背包X = 背包页面.xPositionOnScreen;
            int 背包Y = 背包页面.yPositionOnScreen;
            int 背包宽度 = 背包页面.width;
            int 背包高度 = 背包页面.height;
            int 面板宽度 = 160;
            int 面板高度 = 140;
            int 左边距 = 20;
            int 面板X = 背包X - 面板宽度 - 左边距;
            int 面板Y = 背包Y + (背包高度 - 面板高度) / 2; 
            IClickableMenu.drawTextureBox(spriteBatch, Game1.menuTexture, new Rectangle(0, 256, 60, 60), 面板X, 面板Y, 面板宽度, 面板高度, Color.White);        
            string 标题 = "背包负重";
            Vector2 标题尺寸 = Game1.dialogueFont.MeasureString(标题);
            Vector2 标题位置 = new(面板X + (面板宽度 - 标题尺寸.X) / 2, 面板Y + 15);
            Utility.drawTextWithShadow(spriteBatch, 标题, Game1.dialogueFont, 标题位置, Game1.textColor);
            string 负重数值文本 = $"{当前负重} / {基础负重上限}";
            Vector2 数值尺寸 = Game1.smallFont.MeasureString(负重数值文本);
            Vector2 数值位置 = new(面板X + (面板宽度 - 数值尺寸.X) / 2, 面板Y + 55);
            Color 数值颜色 = 负重比例 switch
            {
                >= 1.5f => Color.Red,
                >= 1.2f => Color.Orange,
                >= 0.8f => Color.Yellow,
                _ => Color.LightGreen
            };

            Utility.drawTextWithShadow(spriteBatch, 负重数值文本, Game1.smallFont, 数值位置, 数值颜色);
            int 进度条X = 面板X + 20;
            int 进度条Y = 面板Y + 80;
            int 进度条宽度 = 面板宽度 - 40;
            int 进度条高度 = 20;
            绘制负重进度条(spriteBatch, 进度条X, 进度条Y, 进度条宽度, 进度条高度, 负重比例);
            string 状态提示 = 获取负重状态提示(当前负重);
            Vector2 状态尺寸 = Game1.smallFont.MeasureString(状态提示);
            Vector2 状态位置 = new(面板X + (面板宽度 - 状态尺寸.X) / 2, 面板Y + 95);
            Utility.drawTextWithShadow(spriteBatch, 状态提示, Game1.smallFont, 状态位置, 数值颜色);
        }

        private static void 绘制负重进度条(SpriteBatch spriteBatch, int x, int y, int width, int height, float 进度)
        {
            spriteBatch.Draw(Game1.staminaRect, new Rectangle(x, y, width, height), new Color(60, 60, 60, 200));
            Color 进度颜色 = 进度 switch
            {
                >= 1.5f => Color.Red,
                >= 1.2f => Color.Orange,
                >= 0.8f => Color.Yellow,
                _ => Color.LightGreen
            };

            int 进度宽度 = (int)(width * Math.Min(进度 / 1.5f, 1f));
            spriteBatch.Draw(Game1.staminaRect, new Rectangle(x, y, 进度宽度, height), 进度颜色);
            int 超重标记位置 = (int)(width * (超重阈值 / (float)基础负重上限 / 1.5f));
            int 严重超重标记位置 = (int)(width * (严重超重阈值 / (float)基础负重上限 / 1.5f));

            spriteBatch.Draw(Game1.staminaRect, new Rectangle(x + 超重标记位置, y, 2, height), Color.White);
            spriteBatch.Draw(Game1.staminaRect, new Rectangle(x + 严重超重标记位置, y, 2, height), Color.White);
            spriteBatch.Draw(Game1.staminaRect, new Rectangle(x, y, width, 1), Color.Black);
            spriteBatch.Draw(Game1.staminaRect, new Rectangle(x, y + height - 1, width, 1), Color.Black);
            spriteBatch.Draw(Game1.staminaRect, new Rectangle(x, y, 1, height), Color.Black);
            spriteBatch.Draw(Game1.staminaRect, new Rectangle(x + width - 1, y, 1, height), Color.Black);
        }

        private static string 获取负重状态提示(int 当前负重)
        {
            return 当前负重 switch
            {
                >= 严重超重阈值 => "严重超重",
                >= 超重阈值 => "超重",
                >= 基础负重上限 => "满载",
                _ => "正常"
            };
        }
    }
}